﻿//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
//
//*********************************************************

#pragma once
#include "pch.h"
#include <concrt.h>


namespace SharpDepend_UWP_DirectXInterop
{
	class ColorUInt
	{
	public:
		unsigned char B;
		unsigned char G;
		unsigned char R;
		unsigned char A;
	};

	class Vector2Double
	{
	public:
		double X;
		double Y;
	};

    // Base class for a SwapChainPanel-based DirectX rendering surface to be used in XAML apps.
    [Windows::Foundation::Metadata::WebHostHidden]
    public ref class DirectXPanelBase : public Windows::UI::Xaml::Controls::SwapChainPanel
    {
	public:

		void BeginDraw()
		{
			OnBeginDraw();
		}
		void DrawRectangle(
			float x1, float y1, float x2, float y2,
			float r, float g, float b, float a,
			int textureId,
			float td_x1, float td_y1, float td_x2, float td_y2,
			int textureWidth, int textureHeight)
		{
			OnDrawRectangle(x1, y1, x2, y2, r, g, b, a, textureId, td_x1, td_y1, td_x2, td_y2, textureWidth, textureHeight);
		}
		void DrawLine(
			float x1, float y1, float x2, float y2,
			float r, float g, float b, float a)
		{
			OnDrawLine(x1, y1, x2, y2, r, g, b, a);
		}
		void DrawCircle(
			float x, float y, float radius,
			float r, float g, float b, float a)
		{
			OnDrawCircle(x, y, radius, r, g, b, a);
		}
		void DrawTriangles(long long vertices, int verticesLength, unsigned short* indices, int indicesLength, long long colors, int colorLength)
		{
			// Convert to native.
			Vector2Double* verticesNative = reinterpret_cast<Vector2Double*>(vertices);
			ColorUInt* colorsNative = reinterpret_cast<ColorUInt*>(colors);

			OnDrawTriangles(verticesNative, verticesLength, indices, indicesLength, colorsNative, colorLength);
		}
		void EndDraw()
		{
			OnEndDraw();
		}

		void __cdecl RegisterTexture(int id, int* data, int dataLength, int width, int height)
		{
			OnRegisterTexture(id, data, dataLength, width, height);
		}
		void UnregisterTexture(int id)
		{
			OnUnregisterTexture(id);
		}
		void UpdateTexture(int id, int* data, int width, int height)
		{
			OnUpdateTexture(id, data, width, height);
		}

    protected private:
        DirectXPanelBase();

		void virtual OnBeginDraw() {}
		void virtual OnDrawRectangle(
			float x1, float y1, float x2, float y2,
			float r, float g, float b, float a,
			int textureId,
			float td_x1, float td_y1, float td_x2, float td_y2,
			int textureWidth, int textureHeight) {}
		void virtual OnDrawLine(
			float x1, float y1, float x2, float y2,
			float r, float g, float b, float a) {}
		void virtual OnDrawCircle(
			float x, float y, float radius,
			float r, float g, float b, float a) {}
		void virtual OnDrawTriangles(Vector2Double* vertices, int verticesLength, unsigned short* indices, int indicesLength, ColorUInt* colors, int colorLength) {}
		void virtual OnEndDraw() {}

		void virtual OnRegisterTexture(int id, int* data, int dataLength, int width, int height) {}
		void virtual OnUnregisterTexture(int id) {}
		void virtual OnUpdateTexture(int id, int* data, int width, int height) {};

        virtual void CreateDeviceIndependentResources();
        virtual void CreateDeviceResources();
        virtual void CreateSizeDependentResources();

        virtual void OnDeviceLost();
        virtual void OnSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
        virtual void OnCompositionScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel ^sender, Platform::Object ^args);
        virtual void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);
        virtual void OnResuming(Platform::Object^ sender, Platform::Object^ args) { };

        virtual void Render() { };
        virtual void Present();

		ID3D11DeviceContext1* GetContext() { return m_d3dContext.Get(); }

        Microsoft::WRL::ComPtr<ID3D11Device1>                               m_d3dDevice;
        Microsoft::WRL::ComPtr<ID3D11DeviceContext1>                        m_d3dContext;
        Microsoft::WRL::ComPtr<IDXGISwapChain2>                             m_swapChain;

        Microsoft::WRL::ComPtr<ID2D1Factory2>                               m_d2dFactory;
        Microsoft::WRL::ComPtr<ID2D1Device>                                 m_d2dDevice;
        Microsoft::WRL::ComPtr<ID2D1DeviceContext>                          m_d2dContext;
        Microsoft::WRL::ComPtr<ID2D1Bitmap1>                                m_d2dTargetBitmap;

        D2D1_COLOR_F                                                        m_backgroundColor;
        DXGI_ALPHA_MODE                                                     m_alphaMode;

        bool                                                                m_loadingComplete;

        Concurrency::critical_section                                       m_criticalSection;

        float                                                               m_renderTargetHeight;
        float                                                               m_renderTargetWidth;        

        float                                                               m_compositionScaleX;
        float                                                               m_compositionScaleY;

        float                                                               m_height;
        float                                                               m_width;

		// Transform used for display orientation.
		DirectX::XMFLOAT4X4 m_orientationTransform3D;
		Windows::Graphics::Display::DisplayOrientations m_orientation;
		Windows::Foundation::Size m_orientedScreenSize;
    };
}